/*
   FieldVis - A Tool for Visualizing Astrophysical Magnetohydrodynamic Flow
   
   Copyright (C) 2006 - 2008     FieldVis Development Team
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   File        : camera.cpp
   Author      : Richard W. Kaszeta  (kaszeta@me.umn.edu)
                 You can freely use this code but I require that I be
                 given credit for it.
                 
   Description : Provides the function glDumpWindowPPM() which uses
                 glReadPixel to query the current GL frame buffer and write
                 that buffer to the specified filename in PPM Binary (P6) format.

                 Useful for producing screenshots and animations (just call it
                 once every time you update the frame, or call it from glutIdleFunc).
                 And since it uses straight GL and not X calls, it should work
                 for both OpenGL and Mesa.
  
                 Usage: glDumpWindowPPM("filename",width,height);
*/

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <GL/glu.h>

#define RGB 3                   /* PPM files has 3 bytes of color
                                   levels per image pixel */
#define RGBA 4                  /* The GL Buffer, however, has 4 bytes
                                   of color info since it includes an
                                   alpha channel */

void glDumpWindowPPM(const char * filename, int win_width, int win_height)
{
   int i,j,k,l;                  /* Counter variables */
   GLubyte *buffer;              /* The GL Frame Buffer */
   unsigned char *ibuffer;       /* The PPM Output Buffer */
   FILE *fp;                     /* The PPM File */

   /* Allocate memory for the the frame buffer and output buffer */
   buffer = (GLubyte *) malloc(win_width*win_height*RGBA);
   ibuffer = (unsigned char *) malloc(win_width*win_height*RGB);

   /* Read window contents from GL frame buffer with glReadPixels */
   glFinish();
   glReadPixels(0,0,win_width,win_height,GL_RGBA,GL_UNSIGNED_BYTE,buffer);

   /* Open the output file */
   printf("file name is: %s\n", filename);
   fp = fopen(filename, "w");

   /* Write a proper P6 PPM header */
   fprintf(fp, "P6\n# CREATOR: glDumpWindowPPM() by R W Kaszeta\n%d %d\n%d\n",
           win_width, win_height, UCHAR_MAX);

   /* Loop through the frame buffer data, writing to the PPM file.  Be careful
      to account for the frame buffer having 4 bytes per pixel while the
      output file has 3 bytes per pixel */
   l=0;
   for (i=0; i<win_height; i++)
   { /* For each row */
      for (j=0; j<win_width; j++)
      { /* For each column */
         for (k=0; k<RGB; k++)
         { /* For each RGB component */
            ibuffer[l++] = (unsigned char)
                           *(buffer + (RGBA*((win_height-1-i)*win_width+j)+k));
         } /* end RGB */
      } /* end column */
   } /* end row */

   /* Write output buffer to the file */
   fwrite(ibuffer, sizeof(unsigned char), RGB*win_width*win_height, fp);
   fclose(fp);
   free(buffer);
   free(ibuffer);

   /* Debugging messages: */
   printf("Wrote %d x %d pixels image to file (%d bytes)\n",
          win_width, win_height, RGB*win_width*win_height);
}

